package com.taishi.library;

import com.taishi.library.util.AnimatorValueUtil;
import com.taishi.library.util.Constant;
import com.taishi.library.util.MiscUtil;
import com.taishi.library.util.ViewUtils;
import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorGroup;
import ohos.agp.animation.AnimatorValue;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.utils.Color;
import ohos.app.Context;

import java.util.ArrayList;
import java.util.List;

/**
 * 柱状体组件
 *
 * @author name
 * @since 2021-04-02
 */
public class Indicator extends Component implements Component.DrawTask, Component.EstimateSizeListener,
        ComponentContainer.ArrangeListener {
    private static final int NORMAL_BARNUM = 3;
    private static final int NORMAL_STEMNUM = 10;
    private static final int NORMAL_TIME = 20000;

    private static final int DEFALT_SIZE = 10;
    private static final float DEFALT_SPACE = 0.2f;
    private static final float DEFALT_WIDTH = 0.8f;
    private Paint paint;
    private int stepNum;

    private int duration;
    private int barNum;
    private Color barColor;

    private int viewHeight;
    private int viewWidth;

    private List<AnimatorValue> animList = new ArrayList<>();

    private List<AnimatorValueUtil> animatorValueUtils = new ArrayList<>();

    /**
     * 构造方法
     *
     * @param context
     */
    public Indicator(Context context) {
        super(context);
    }

    /**
     * 构造方法
     *
     * @param context
     * @param attrSet
     */
    public Indicator(Context context, AttrSet attrSet) {
        super(context, attrSet);
        init(attrSet);
    }

    /**
     * 构造方法
     *
     * @param context
     * @param attrs
     * @param defStyleAttr
     */
    public Indicator(Context context, AttrSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    private void init(AttrSet attrSet) {
        barNum = ViewUtils.getInstance().getAttrIntValue(attrSet, Constant.INDICATOR_BAR_NUM, NORMAL_BARNUM);
        stepNum = ViewUtils.getInstance().getAttrIntValue(attrSet, Constant.INDICATOR_STEP_NUM, NORMAL_STEMNUM);
        duration = ViewUtils.getInstance().getAttrIntValue(attrSet, Constant.INDICATOR_DURATION, NORMAL_TIME);
        barColor = ViewUtils.getInstance().getAttrColorValue(attrSet, Constant.INDICATOR_BAR_COLOR, Color.WHITE);
        List<Float> floatList = getGraduateFloatList(stepNum, viewHeight);
        generateAnim(floatList);
    }

    /**
     * 同原库onlayout方法
     *
     * @param left
     * @param top
     * @param right
     * @param bottom
     * @return boolean
     */
    @Override
    public boolean onArrange(int left, int top, int right, int bottom) {
        return false;
    }

    /**
     * 此方法加载onDraw方法以重新绘制组件
     */
    @Override
    public void invalidate() {
        super.invalidate();
        addDrawTask(this::onDraw);
    }

    @Override
    public void onDraw(Component component, Canvas canvas) {
        paint = new Paint();
        paint.setColor(barColor);
        drawIndicator(component, canvas);
    }

    /**
     * 同onMeasure方法
     *
     * @param widthMeasureSpec
     * @param heightMeasureSpec
     * @return boolean
     */
    @Override
    public boolean onEstimateSize(int widthMeasureSpec, int heightMeasureSpec) {
        viewWidth = MiscUtil.measure(widthMeasureSpec, DEFALT_SIZE);
        viewHeight = MiscUtil.measure(heightMeasureSpec, DEFALT_SIZE);
        setEstimatedSize(viewWidth, viewHeight);

        return false;
    }

    private List<Float> getGraduateFloatList(int arraySize, int max) {
        List<Float> floatList = new ArrayList();
        double dividedMax = max / arraySize;

        for (int ii = 1; ii <= arraySize; ii++) {
            double aa = ii * dividedMax;
            floatList.add((float) aa);
        }
        floatList.set(floatList.size() - 1, floatList.get(0));

        return floatList;
    }

    private void generateAnim(List<Float> floatList) {
        animList = new ArrayList<>();
        animatorValueUtils.clear();
        AnimatorValueUtil animatorValueUtil;

        for (int ii = 0; ii < barNum; ii++) {
            float[] floatArray = new float[floatList.size()];
            int jj = 0;
            for (Float ff : floatList) {
                floatArray[jj++] = (float) (Math.random());
            }
            floatArray[floatArray.length - 1] = floatArray[0];

            animatorValueUtil = new AnimatorValueUtil();

            animatorValueUtil.ofFloat(floatArray);

            animatorValueUtils.add(animatorValueUtil);

            AnimatorValue anim = new AnimatorValue();
            anim.setDuration(duration);
            anim.setLoopedCount(AnimatorValue.INFINITE);
            anim.setCurveType(Animator.CurveType.ACCELERATE_DECELERATE);
            int finalI = ii;
            anim.setValueUpdateListener(new AnimatorValue.ValueUpdateListener() {
                @Override
                public void onUpdate(AnimatorValue animatorValue, float move) {
                    animatorValueUtils.get(finalI).getValue(move);
                    invalidate();
                }
            });
            anim.start();
            animList.add(anim);

        }
        AnimatorGroup animatorGroup = new AnimatorGroup();
        animatorGroup.runParallel();
    }

    private void drawIndicator(Component component, Canvas canvas) {
        // 计算每个柱状图间隔
        double spaceWidth = component.getWidth() * DEFALT_SPACE / (barNum - 1);

        // 计算每个柱状图宽度
        double barWidth = component.getWidth() * DEFALT_WIDTH / barNum;
        double sumWidth = spaceWidth + barWidth;
        for (int ii = 0; ii < barNum; ii++) {
            double hightRan = animatorValueUtils.get(ii).getCurrentValue() * (component.getHeight() * DEFALT_WIDTH);
            float height = (float) hightRan;
            canvas.drawRect(
                    (float) (ii * sumWidth), // left
                    component.getHeight() - height, // height, // top
                    (float) (ii * sumWidth + barWidth), // right
                    component.getHeight(), // bottom
                    paint // Paint
            );

            if (ii == barNum - 1) {
                float heightLast = animatorValueUtils.get(ii).getCurrentValue();
                canvas.drawRect(
                        (float) ((ii + 1) * sumWidth), // left
                        component.getHeight() - heightLast, // height, // top
                        (float) ((ii + 1) * sumWidth + barWidth), // right
                        component.getHeight(), // bottom
                        paint // Paint
                );
            }
        }
    }

    public void setStepNum(int stepNum) {
        this.stepNum = stepNum;
    }

    public void setDuration(int duration) {
        this.duration = duration;
    }

    public void setBarNum(int barNum) {
        this.barNum = barNum;
    }

    public void setBarColor(Color barColor) {
        this.barColor = barColor;
    }

}
